//
// Created by wkm on 2024-04-23.
//

#ifndef AES128CHIPSYSTEMC_AES128EN_H
#define AES128CHIPSYSTEMC_AES128EN_H

#include "mixcolumns.h"
#include "schedulekey.h"
#include "shiftrows.h"
#include "../ROM/sbox.h"
#include "../core_module/CONSTANT.h"

SC_MODULE(aes128en) {
    sc_in<bool> clk, start, reset;
    sc_in<sc_uint<DATA_SIZE>> key1, key2, key3, key4, key5, key6, key7, key8,
            key9, key10, key11, key12, key13, key14, key15, key16;
    sc_in<sc_uint<DATA_SIZE>> pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8,
            pt9, pt10, pt11, pt12, pt13, pt14, pt15, pt16;
    sc_out<exe_state> done;
    sc_out<sc_uint<DATA_SIZE>> ct1, ct2, ct3, ct4, ct5, ct6, ct7, ct8,
            ct9, ct10, ct11, ct12, ct13, ct14, ct15, ct16;

    sc_signal<sc_uint<DATA_SIZE>> sbox_input_1, sbox_input_2, sbox_input_3, sbox_input_4,
            sbox_input_5, sbox_input_6, sbox_input_7, sbox_input_8,
            sbox_input_9, sbox_input_10, sbox_input_11, sbox_input_12,
            sbox_input_13, sbox_input_14, sbox_input_15, sbox_input_16,
            sbox_output_1, sbox_output_2, sbox_output_3, sbox_output_4,
            sbox_output_5, sbox_output_6, sbox_output_7, sbox_output_8,
            sbox_output_9, sbox_output_10, sbox_output_11, sbox_output_12,
            sbox_output_13, sbox_output_14, sbox_output_15, sbox_output_16,

            sr_in_1, sr_in_2, sr_in_3, sr_in_4, sr_in_5, sr_in_6, sr_in_7, sr_in_8,
            sr_in_9, sr_in_10, sr_in_11, sr_in_12, sr_in_13, sr_in_14, sr_in_15, sr_in_16,
            sr_out_1, sr_out_2, sr_out_3, sr_out_4, sr_out_5, sr_out_6, sr_out_7, sr_out_8,
            sr_out_9, sr_out_10, sr_out_11, sr_out_12, sr_out_13, sr_out_14, sr_out_15, sr_out_16,

            init_key_1, init_key_2, init_key_3, init_key_4,
            init_key_5, init_key_6, init_key_7, init_key_8,
            init_key_9, init_key_10, init_key_11, init_key_12,
            init_key_13, init_key_14, init_key_15, init_key_16,
            round_key_1, round_key_2, round_key_3, round_key_4, round_key_5, round_key_6, round_key_7, round_key_8,
            round_key_9, round_key_10, round_key_11, round_key_12, round_key_13, round_key_14, round_key_15, round_key_16,

            mx_in_1, mx_in_2, mx_in_3, mx_in_4, mx_in_5, mx_in_6, mx_in_7, mx_in_8,
            mx_in_9, mx_in_10, mx_in_11, mx_in_12, mx_in_13, mx_in_14, mx_in_15, mx_in_16,
            mx_out_1, mx_out_2, mx_out_3, mx_out_4, mx_out_5, mx_out_6, mx_out_7, mx_out_8,
            mx_out_9, mx_out_10, mx_out_11, mx_out_12, mx_out_13, mx_out_14, mx_out_15, mx_out_16;

    sc_signal<exe_state> sbox_done, sr_done;
    sc_signal<bool> sbox_enread, sr_reset, sk_reset, mx_reset, sk_start, sr_start, mx_start;

    sc_signal<exe_state> sk_done, sk_can_read, mx_done;
    sc_signal<sc_uint<4>> sk_get_round;
    sc_signal<exe_state> done_next_state;

    sc_uint<DATA_SIZE> compute_round_NO; // 记忆第几轮
    sc_uint<DATA_SIZE> key[16], res[16];
    basic_op_state op_state, op_state_next;
    bool sk_start_first_flag;

    sbox *my_sbox;
    shiftrows *my_shiftrows;
    mixcolumns *my_mixcolumns;
    schedulekey *my_schedulekey;

    void prc_aes128();

    SC_CTOR(aes128en) {
        my_sbox = new sbox("my_sbox");

        my_sbox->en_read(sbox_enread);
        my_sbox->done(sbox_done);
        my_sbox->clk(clk);
        my_sbox->addr1(sbox_input_1);
        my_sbox->addr2(sbox_input_2);
        my_sbox->addr3(sbox_input_3);
        my_sbox->addr4(sbox_input_4);
        my_sbox->addr5(sbox_input_5);
        my_sbox->addr6(sbox_input_6);
        my_sbox->addr7(sbox_input_7);
        my_sbox->addr8(sbox_input_8);
        my_sbox->addr9(sbox_input_9);
        my_sbox->addr10(sbox_input_10);
        my_sbox->addr11(sbox_input_11);
        my_sbox->addr12(sbox_input_12);
        my_sbox->addr13(sbox_input_13);
        my_sbox->addr14(sbox_input_14);
        my_sbox->addr15(sbox_input_15);
        my_sbox->addr16(sbox_input_16);
        my_sbox->out_data1(sbox_output_1);
        my_sbox->out_data2(sbox_output_2);
        my_sbox->out_data3(sbox_output_3);
        my_sbox->out_data4(sbox_output_4);
        my_sbox->out_data5(sbox_output_5);
        my_sbox->out_data6(sbox_output_6);
        my_sbox->out_data7(sbox_output_7);
        my_sbox->out_data8(sbox_output_8);
        my_sbox->out_data9(sbox_output_9);
        my_sbox->out_data10(sbox_output_10);
        my_sbox->out_data11(sbox_output_11);
        my_sbox->out_data12(sbox_output_12);
        my_sbox->out_data13(sbox_output_13);
        my_sbox->out_data14(sbox_output_14);
        my_sbox->out_data15(sbox_output_15);
        my_sbox->out_data16(sbox_output_16);

        my_shiftrows = new shiftrows("my_shiftrows");
        my_shiftrows->clk(clk);
        my_shiftrows->reset(sr_reset);
        my_shiftrows->start(sr_start);
        my_shiftrows->done(sr_done);
        my_shiftrows->input_data_1(sr_in_1);
        my_shiftrows->input_data_2(sr_in_2);
        my_shiftrows->input_data_3(sr_in_3);
        my_shiftrows->input_data_4(sr_in_4);
        my_shiftrows->input_data_5(sr_in_5);
        my_shiftrows->input_data_6(sr_in_6);
        my_shiftrows->input_data_7(sr_in_7);
        my_shiftrows->input_data_8(sr_in_8);
        my_shiftrows->input_data_9(sr_in_9);
        my_shiftrows->input_data_10(sr_in_10);
        my_shiftrows->input_data_11(sr_in_11);
        my_shiftrows->input_data_12(sr_in_12);
        my_shiftrows->input_data_13(sr_in_13);
        my_shiftrows->input_data_14(sr_in_14);
        my_shiftrows->input_data_15(sr_in_15);
        my_shiftrows->input_data_16(sr_in_16);
        my_shiftrows->output_data_1(sr_out_1);
        my_shiftrows->output_data_2(sr_out_2);
        my_shiftrows->output_data_3(sr_out_3);
        my_shiftrows->output_data_4(sr_out_4);
        my_shiftrows->output_data_5(sr_out_5);
        my_shiftrows->output_data_6(sr_out_6);
        my_shiftrows->output_data_7(sr_out_7);
        my_shiftrows->output_data_8(sr_out_8);
        my_shiftrows->output_data_9(sr_out_9);
        my_shiftrows->output_data_10(sr_out_10);
        my_shiftrows->output_data_11(sr_out_11);
        my_shiftrows->output_data_12(sr_out_12);
        my_shiftrows->output_data_13(sr_out_13);
        my_shiftrows->output_data_14(sr_out_14);
        my_shiftrows->output_data_15(sr_out_15);
        my_shiftrows->output_data_16(sr_out_16);

        my_schedulekey = new schedulekey("my_schedulekey");
        my_schedulekey->reset(sk_reset);
        my_schedulekey->start(sk_start);
        my_schedulekey->clk(clk);
        my_schedulekey->done(sk_done);
        my_schedulekey->can_read(sk_can_read);
        my_schedulekey->get_round(sk_get_round);
        my_schedulekey->init_key_1(init_key_1);
        my_schedulekey->init_key_2(init_key_2);
        my_schedulekey->init_key_3(init_key_3);
        my_schedulekey->init_key_4(init_key_4);
        my_schedulekey->init_key_5(init_key_5);
        my_schedulekey->init_key_6(init_key_6);
        my_schedulekey->init_key_7(init_key_7);
        my_schedulekey->init_key_8(init_key_8);
        my_schedulekey->init_key_9(init_key_9);
        my_schedulekey->init_key_10(init_key_10);
        my_schedulekey->init_key_11(init_key_11);
        my_schedulekey->init_key_12(init_key_12);
        my_schedulekey->init_key_13(init_key_13);
        my_schedulekey->init_key_14(init_key_14);
        my_schedulekey->init_key_15(init_key_15);
        my_schedulekey->init_key_16(init_key_16);
        my_schedulekey->out_key_1(round_key_1);
        my_schedulekey->out_key_2(round_key_2);
        my_schedulekey->out_key_3(round_key_3);
        my_schedulekey->out_key_4(round_key_4);
        my_schedulekey->out_key_5(round_key_5);
        my_schedulekey->out_key_6(round_key_6);
        my_schedulekey->out_key_7(round_key_7);
        my_schedulekey->out_key_8(round_key_8);
        my_schedulekey->out_key_9(round_key_9);
        my_schedulekey->out_key_10(round_key_10);
        my_schedulekey->out_key_11(round_key_11);
        my_schedulekey->out_key_12(round_key_12);
        my_schedulekey->out_key_13(round_key_13);
        my_schedulekey->out_key_14(round_key_14);
        my_schedulekey->out_key_15(round_key_15);
        my_schedulekey->out_key_16(round_key_16);

        my_mixcolumns = new mixcolumns("my_mixcolumns");
        my_mixcolumns->clk(clk);
        my_mixcolumns->start(mx_start);
        my_mixcolumns->reset(mx_reset);
        my_mixcolumns->done(mx_done);
        my_mixcolumns->input_data_1(mx_in_1);
        my_mixcolumns->input_data_2(mx_in_2);
        my_mixcolumns->input_data_3(mx_in_3);
        my_mixcolumns->input_data_4(mx_in_4);
        my_mixcolumns->input_data_5(mx_in_5);
        my_mixcolumns->input_data_6(mx_in_6);
        my_mixcolumns->input_data_7(mx_in_7);
        my_mixcolumns->input_data_8(mx_in_8);
        my_mixcolumns->input_data_9(mx_in_9);
        my_mixcolumns->input_data_10(mx_in_10);
        my_mixcolumns->input_data_11(mx_in_11);
        my_mixcolumns->input_data_12(mx_in_12);
        my_mixcolumns->input_data_13(mx_in_13);
        my_mixcolumns->input_data_14(mx_in_14);
        my_mixcolumns->input_data_15(mx_in_15);
        my_mixcolumns->input_data_16(mx_in_16);
        my_mixcolumns->out_data_1(mx_out_1);
        my_mixcolumns->out_data_2(mx_out_2);
        my_mixcolumns->out_data_3(mx_out_3);
        my_mixcolumns->out_data_4(mx_out_4);
        my_mixcolumns->out_data_5(mx_out_5);
        my_mixcolumns->out_data_6(mx_out_6);
        my_mixcolumns->out_data_7(mx_out_7);
        my_mixcolumns->out_data_8(mx_out_8);
        my_mixcolumns->out_data_9(mx_out_9);
        my_mixcolumns->out_data_10(mx_out_10);
        my_mixcolumns->out_data_11(mx_out_11);
        my_mixcolumns->out_data_12(mx_out_12);
        my_mixcolumns->out_data_13(mx_out_13);
        my_mixcolumns->out_data_14(mx_out_14);
        my_mixcolumns->out_data_15(mx_out_15);
        my_mixcolumns->out_data_16(mx_out_16);

        SC_METHOD(prc_aes128);
        sensitive << clk.pos();
    }

    void end_of_elaboration() {
        cout << "end_of_elaboration" << endl;
    }


    ~aes128en() {
        delete my_sbox;
        delete my_shiftrows;
        delete my_mixcolumns;
        delete my_schedulekey;
    }
};


#endif //AES128CHIPSYSTEMC_AES128EN_H
